package com.enation.app.javashop.core.pagedata.service.impl;

import com.enation.app.javashop.core.base.context.Region;
import com.enation.app.javashop.core.base.message.CmsManageMsg;
import com.enation.app.javashop.core.base.rabbitmq.AmqpExchange;
import com.enation.app.javashop.core.client.goods.GoodsClient;
import com.enation.app.javashop.core.geo.model.TencentLocation;
import com.enation.app.javashop.core.geo.service.TencentManager;
import com.enation.app.javashop.core.goods.model.vo.CacheGoods;
import com.enation.app.javashop.core.pagedata.model.MenuDate;
import com.enation.app.javashop.core.pagedata.model.PageData;
import com.enation.app.javashop.core.pagedata.model.enums.*;
import com.enation.app.javashop.core.pagedata.model.vo.PageListQueryVo;
import com.enation.app.javashop.core.pagedata.service.PageDataManager;
import com.enation.app.javashop.core.system.SystemErrorCode;
import com.enation.app.javashop.core.system.enums.ClientType;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.database.Page;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.util.IDataUtils;
import com.enation.app.javashop.framework.util.JsonUtil;
import com.enation.app.javashop.framework.util.SqlUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import com.enation.app.javashop.framework.validation.annotation.Operation;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 楼层业务类
 *
 * @author fk
 * @version v1.0
 * @since v7.0.0
 * 2018-05-21 16:39:22
 */
@Service
public class PageDataManagerImpl implements PageDataManager {

    @Autowired
    @Qualifier("systemDaoSupport")
    private DaoSupport daoSupport;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private GoodsClient goodsClient;

    @Autowired
    private TencentManager tencentManager;

    protected final Log logger = LogFactory.getLog(this.getClass());

    /**
     * john 新增
     * @param page
     * @param pageSize
     * @param storeId
     */
    @Override
    public Page listOfStoreId(int page, int pageSize,String pageType, Integer storeId) {
        String sql = "select * from es_page  where owner_type=3 and  store_id = ? and page_type=?";
        return this.daoSupport.queryForPage(sql , page, pageSize,storeId,pageType);
    }


    /**
     * john 新增
     */
    @Override
    public Page listOfPlatform(PageListQueryVo pageListQueryVo) {
        List<Object> term = new ArrayList<>();
        StringBuilder sql = new StringBuilder("select * from es_page  where 1=1 ");
        if(StringUtil.notEmpty(pageListQueryVo.getPageName())){
            sql.append(" and page_name like ?");
            term.add("%" + pageListQueryVo.getPageName() + "%");
        }
        if(StringUtil.notEmpty(pageListQueryVo.getPageType())){
            sql.append(" and page_type = ?");
            term.add(pageListQueryVo.getPageType());
        }
        if(StringUtil.notEmpty(pageListQueryVo.getOwnerType())){
            sql.append(" and owner_type = ?");
            term.add(pageListQueryVo.getOwnerType());
        }
        if(StringUtil.notEmpty(pageListQueryVo.getCity())){
            sql.append(" and city like ?");
            term.add("%" + pageListQueryVo.getCity() + "%");
        }
        if(pageListQueryVo.getState() != null){
            sql.append(" and state = ?");
            term.add(pageListQueryVo.getState());
        }
        if(pageListQueryVo.getPageId() != null){
            sql.append(" and page_id = ?");
            term.add(pageListQueryVo.getPageId());
        }
        sql.append(" order by page_id desc");

        return this.daoSupport.queryForPage(sql.toString() , pageListQueryVo.getPageNo(),  pageListQueryVo.getPageSize(),term.toArray());
    }


    /**
     * john 新增
     */
    @Override
    public Page listOfAgentId(int page, int pageSize, String pageType, Integer agentId) {
        String sql = "select * from es_page  where owner_type = 2 and agent_id =? and page_type=?";
        return this.daoSupport.queryForPage(sql , page, pageSize,agentId,pageType);
    }



    @Override
    public Page list(int page, int pageSize) {
        String sql = "select * from es_page  ";
        return this.daoSupport.queryForPage(sql, page, pageSize, Page.class);
    }

    @Override
    @Transactional(value = "systemTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public PageData add(PageData page) {

        //检验页面的合规则 ， 新增
        validatePage(page);

        this.daoSupport.insert(page);
        //发送消息
        this.sendFocusChangeMessage(page.getClientType());
        return page;
    }

    @Override
    @Transactional(value = "systemTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public PageData edit(PageData page, Integer id) {
        page.setPageId(id);
        validatePage(page);

        this.daoSupport.update(page, id);
        //发送消息
        this.sendFocusChangeMessage(page.getClientType());
        return page;
    }

    @Override
    @Transactional(value = "systemTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void delete(Integer id) {
        this.daoSupport.delete(PageData.class, id);
        //发送消息
//        PageData page = this.getModel(id);
//        this.sendFocusChangeMessage(page.getClientType());
    }

    @Override
    public PageData getModel(Integer id) {
        return this.daoSupport.queryForObject(PageData.class, id);
    }


    @Override
    public PageData queryPageData(String clientType, String pageType) {
        PageData page = this.getByType(clientType, pageType);
        if (page == null) {
            throw new ServiceException(SystemErrorCode.E806.code(), "楼层找不到");
        }
        constructPageData(page);
        return page;
    }

    /**
     * john 新增
     */
    @Override
    public PageData queryPageData(String clientType, String pageType, Integer pageId) {
        PageData page = this.getByType(clientType, pageType);
        if (page == null) {
            throw new ServiceException(SystemErrorCode.E806.code(), "楼层找不到");
        }
        constructPageData(page);
        return page;
    }

    @Override
    @Operation
    @Transactional(value = "systemTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public PageData editByType(PageData pageData) {
        PageData data = this.getByType(pageData.getClientType(), pageData.getPageType());
        //首次保存
        if (data == null) {
            this.daoSupport.insert(pageData);
            pageData.setPageId(this.daoSupport.getLastId(""));
        } else {
            this.daoSupport.update(pageData, data.getPageId());
            pageData.setPageId(data.getPageId());
        }

        return pageData;
    }

    @Override
    public PageData getByType(String clientType, String pageType) {

        String sql = "select * from es_page where client_type = ? and page_type = ? and owner_type = 1";

        PageData page = this.daoSupport.queryForObject(sql, PageData.class, clientType, pageType);

        constructPageData(page);

        return page;
    }

    @Override
    public PageData getOne(PageData pageData) {

        String sql = "select * from es_page where client_type = ? and owner_type = ? and state=? and page_type =? ";

        return this.daoSupport.queryForObject(sql, PageData.class, pageData.getClientType(), pageData.getOwnerType(),pageData.getState(),pageData.getPageType());
    }


    /**
     * 页面上架
     */
    @Override
    @Transactional(value = "systemTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean putaway(Integer id) {
        Map<String, Object> fieldsMap = new HashMap<>();
        fieldsMap.put("state", PageStateEnum.ACTIVE.getValue());
        Map<String, Object> whereMap = new HashMap<>();
        whereMap.put("page_id",id);
        int rows = this.daoSupport.update("es_page",fieldsMap,whereMap);
        if(rows < 1){
            return false;
        }else if(rows>1){
            throw new RuntimeException("操作了多条记录");
        }else{
            return true;
        }

    }

    /**
     * 页面下架
     */
    @Override
    @Transactional(value = "systemTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean soldOut(Integer id) {
        Map fieldsMap = new HashMap<>();
        fieldsMap.put("state",3);
        Map whereMap = new HashMap<>();
        whereMap.put("page_id",id);
        int rows = this.daoSupport.update("es_page",fieldsMap,whereMap);
        if(rows < 1){
            return false;
        }else if(rows>1){
            throw new RuntimeException("操作了多条记录");
        }else{
            return true;
        }
    }

    /**
     * 设置APP首页
     */
    @Override
    public boolean setIndexPage(Integer pageId,String homePageType, Region region) {
        // 平台首页
        if(region==null){
            IndexPageTypeEnum.PLATFORM_INDEX.setIndexPage(this, pageId,homePageType,null);
        }
        // 城市首页
        if(region!=null){
            IndexPageTypeEnum.CITY_INDEX.setIndexPage(this, pageId,homePageType,region);
        }
        return true;
    }

    @Override
    public PageData getIndexPage(String clientType,String pageType, String city, Double lng, Double lat) {

        PageData indexPage =null;

        if(lng != null && lat != null){
            // 解析四级地址 根据四级地址查询 自定义页面
            TencentLocation tencentLocation = tencentManager.parseLatLng(lng, lat);
            String townshipStr = tencentLocation.getAddressComponent().getTownshipStr();
            if(StringUtil.notEmpty(townshipStr)){
                indexPage = this.getCityIndexPage(townshipStr,pageType);
            }
            // 四级地址查不到,根据传来的城市查询
            if(indexPage == null){
                indexPage = this.getCityIndexPage(city,pageType);
            }
        }else {
            // 经纬度为空 根据城市查询
            // 优先查询城市首页
            if(!StringUtils.isEmpty(city)){
                indexPage = this.getCityIndexPage(city,pageType);
            }
        }
        // 城市首页为空 查询平台首页
        if(indexPage==null){
            indexPage = this.queryPageData(clientType,pageType);
        }
        return indexPage;
    }

    /**
     * 查询发现页楼层
     */
    @Override
    public PageData getDiscover(String clientType, String city) {
        if(StringUtil.isEmpty(city)){
            String sql = "select * from es_page where client_type = ? and state=? and is_discover=1";
            return this.daoSupport.queryForObject(sql, PageData.class, clientType,PageStateEnum.ACTIVE.getValue());
        }else{
            logger.debug("===========开始查询城市的活动页数据===========");
            String sql = "select * from es_page where client_type = ? and state=? and is_discover=1  and city = ? ";

            PageData page = this.daoSupport.queryForObject(sql, PageData.class, clientType,PageStateEnum.ACTIVE.getValue(),city);
            if(page == null || page.getPageId()==null){
                logger.debug("没有找到对应的活动页数据，准备开始查平台默认的");

                sql = "select * from es_page where client_type = ? and state=? and is_discover=1 and city is null";

                page = this.daoSupport.queryForObject(sql, PageData.class, clientType,PageStateEnum.ACTIVE.getValue());
                logger.debug("=======查询出来的页面数据是=====："+page.getPageId());
            }
            return page;
        }



    }

    @Override
    public PageData getCityIndexPage(String cityStr,String homePageType) {//,String homePageType
        if(cityStr.length()>2){
            cityStr = cityStr.substring(0, 2);
        }
        String sql;
        PageData page;
        if("0".equals(homePageType)){
            sql = "select * from es_page where client_type = ?  and (town like ? or county like ? or city like ? or province like ? ) and state=2 and page_type = '0' and owner_type = 0 ";
            page = this.daoSupport.queryForObject(sql, PageData.class, "APP", cityStr + "%",cityStr + "%",cityStr + "%", cityStr + "%");
        }else {
            sql = "select * from es_page where client_type = ? and page_type = ? and (town like ? or county like ? or city like ? or province like ? ) and state=2 and owner_type = 2 ";
            page = this.daoSupport.queryForObject(sql, PageData.class, "APP", homePageType, cityStr + "%",cityStr + "%",cityStr + "%", cityStr + "%");
        }
        return  page;
    }



    /**
     * 重新渲染楼层数据
     */
    private void constructPageData(PageData page){

        if(page != null && "WAP".equals(page.getClientType())) {
            String pageData = page.getPageData();
            List<HashMap> dataList = JsonUtil.jsonToList(pageData, HashMap.class);
            for (Map map : dataList) {
                List<Map> blockList = (List<Map>) map.get("blockList");
                for (Map blockMap : blockList) {
                    String blockType = (String) blockMap.get("block_type");
                    switch (blockType) {
                        case "GOODS":
                            if("".equals(blockMap.get("block_value")) || blockMap.get("block_value") == null){
                                blockMap.put("block_value", null);
                                return;
                            }
                            Map blockValue = (Map) blockMap.get("block_value");

                            Integer goodsId = StringUtil.toInt(blockValue.get("goods_id"),false);
                            CacheGoods goods = null;
                            try {
                                goods = this.goodsClient.getFromCache(goodsId);
                            } catch (Exception e) {
                                logger.error(e);
                            }
                            //如果商品被删除则返回空数据
                            if (goods == null || goods.getDisabled() == 0) {
                                blockMap.put("block_value", null);
                                break;
                            }
                            blockValue.put("goods_name", goods.getGoodsName());
                            blockValue.put("sn", goods.getSn());
                            blockValue.put("thumbnail", goods.getThumbnail());
                            blockValue.put("seller_name", goods.getSellerName());
                            blockValue.put("goods_image", goods.getThumbnail());
                            blockValue.put("enable_quantity", goods.getEnableQuantity());
                            blockValue.put("quantity", goods.getQuantity());
                            blockValue.put("goods_price", goods.getPrice());
                            blockValue.put("market_enable", goods.getMarketEnable());
                            blockValue.put("is_auth", goods.getIsAuth());

                            break;
                        default:
                            break;
                    }

                }

            }
            page.setPageData(JsonUtil.objectToJson(dataList));
        }
    }

    /**
     * 发送首页变化消息
     */
    private void sendFocusChangeMessage(String clientType) {

        CmsManageMsg cmsManageMsg = new CmsManageMsg();

        if (ClientType.PC.name().equals(clientType)) {
            this.amqpTemplate.convertAndSend(AmqpExchange.PC_INDEX_CHANGE, AmqpExchange.PC_INDEX_CHANGE + "_ROUTING", cmsManageMsg);
        } else {
            this.amqpTemplate.convertAndSend(AmqpExchange.MOBILE_INDEX_CHANGE, AmqpExchange.MOBILE_INDEX_CHANGE + "_ROUTING", cmsManageMsg);
        }
    }


    /**
     * 核验页面的合规性
     */
    private void validatePage(PageData page){
        // 判断页面类型， 如果数据库中存在首页，且编辑的不是此页面，则报非法处理
        if(page.getPageType().equals(PageTypeEnum.INDEX.value())){
            //查询出对应此平台或商户的主页，判断id是否一致。
            String sql = "select * from es_page where store_id = ? and owner_type =? and client_type = ? and page_type=? ";
            PageData pageData = this.daoSupport.queryForObject(sql,PageData.class,page.getStoreId(), OwnerTypeEnum.PLATFORM.value(),page.getClientType(),page.getPageType());
            if(pageData!=null && ! pageData.getPageId().equals(page.getPageId()) ){
                //说明编辑的首页与库中的首页不一样。
                throw new RuntimeException("非法操作，首页已存在，不能自行添加首页");
            }
        }
    }

    @Override
    public Page menuConfigList(PageListQueryVo pageListQueryVo) {
        List<Object> term = new ArrayList<>();
        StringBuilder sql = new StringBuilder(" select * from es_page  where owner_type = 1 ");

        String pageName = pageListQueryVo.getPageName();
        String ownerType = pageListQueryVo.getPageType();
        String province = pageListQueryVo.getProvince();
        String city = pageListQueryVo.getCity();
        String county = pageListQueryVo.getCounty();

        //配置名称
        if(StringUtil.notEmpty(pageName)){
            sql.append(" and page_name like ?");
            term.add("%" + pageName + "%");
        }
        // 配置类型
        if(StringUtil.notEmpty(ownerType)){
            sql.append(" and owner_type = ?");
            term.add(ownerType);
        }
        // 所属城市
        // 省
        if(StringUtil.notEmpty(province)){
            sql.append(" and province = ?");
            term.add( province);
            // 市
            if(StringUtil.notEmpty(city)){
                sql.append(" and city = ?");
                term.add(city);
                //区/县
                if(StringUtil.notEmpty(county)){
                    sql.append(" and county = ?");
                    term.add(county);
                }
            }
        }
        return this.daoSupport.queryForPage(sql.toString() , pageListQueryVo.getPageNo(),  pageListQueryVo.getPageSize(),term.toArray());
    }

    @Override
    public void delMenu(Integer[] ids) {
        List<Object> term = new ArrayList<>();
        String idsStr = SqlUtil.getInSql(ids, term);
        String sql = " update es_page set delete_flag = 0 where page_id in (" + idsStr + ")";
        this.daoSupport.execute(sql, term.toArray());
    }

    @Override
    @Transactional(value = "systemTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public MenuDate addMenu(MenuDate menuDate) {
        cheakDate(menuDate);
        menuDate.setDeleteFlag(1);
        this.daoSupport.insert(menuDate);
        return menuDate;
    }
    @Override
    @Transactional(value = "systemTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public MenuDate udpMenu(MenuDate menuDate, Integer id) {
        cheakDate(menuDate);
        this.daoSupport.update(menuDate,id);
        return menuDate;
    }

    //检验当前数据所选的 配置类型 是否已存在数据
    private void cheakDate(MenuDate menuDate){
        String sql = "  select * from es_page where delete_flag = 1 and  owner_type = ?";
        Integer ownerType = menuDate.getOwnerType();
        String province = menuDate.getProvince();
        String city = menuDate.getCity();
        String county = menuDate.getCounty();
        List list;

        if(ownerType == 2){
            logger.info(StringUtil.isEmpty(province));
            Assert.isTrue(StringUtil.notEmpty(province),"请选择省份！");
            Assert.isTrue(StringUtil.notEmpty(city),"请选择市！");
            // 查询 当前城市在数据库中是否已经存在数据
            sql = sql + " and province = ? and city =? and county =? ";

            // 如何区/县 不存在或传入空字符串，转为null
            if("".equals(county)){
                county = "null";
            }
            //截取省的名字
            if(province.contains("省") || province.contains("市")){
                // 将传来的省名称截取前两位
                province = province.substring(0,province.length()-1);
            }
            list = this.daoSupport.queryForList(sql, ownerType, province, city, county);
        }else{
            // 查询 数据库中没有删除的数据中 是否已经存在平台的数据
            list = daoSupport.queryForList(sql,ownerType);
        }

        if(list != null && list.size() > 0){
            throw new RuntimeException("数据已存在，请确认！");
        }
    }

    @Override
    public void copyPageIndex(Integer pageId){
        PageData pageData = getModel(pageId);
        String historyPageName = pageData.getPageName();
        if(pageData != null){
            pageData.setPageId(null);
            pageData.setPageName(historyPageName+"-副本");
            pageData.setPageType(PageHomeTypeEnum.DEFINED.value().toString());
            pageData.setPageTypeName(PageHomeTypeEnum.DEFINED.description());
            pageData.setOwnerType(OwnerTypeEnum.DEFINED.value());
            pageData.setProvince(null);
            pageData.setCity(null);
            pageData.setCountyId(null);
            pageData.setState(PageStateEnum.SCRIPT.getValue());
            daoSupport.insert(pageData);
        }else {
            throw  new RuntimeException("没有找到微页面!");
        }
    }

    /**
     * 获取本地生活所在的发现页
     */
    @Override
    public PageData getLocalLifeShop(String clientType,Integer ownerType,String pageType, String town) {
        String sql = "select * from es_page where client_type = ? and owner_type = ?  and page_type = ? and " +
                " (province like ? or city like ? or county like ? or town like ? ) and state= 2 ";
        List<Object> term = new ArrayList<>();
        term.add(clientType);
        term.add(ownerType);
        term.add(pageType);
        term.add("%" +town + "%");
        term.add("%" +town + "%");
        term.add("%" +town + "%");
        term.add("%" +town + "%");
        return daoSupport.queryForObject(sql, PageData.class, term.toArray());
    }

}
